﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

/*
 * TODO: create forms to display tabbed graphs and views
 * TODO: set tool tips for buttons (http://www.dotnetspider.com/resources/17072-Setting-ToolTip-for-button-C.aspx)
 *       (http://en.allexperts.com/q/C-3307/Button-ToolTips.htm)
 * TODO: implement worm
 */

namespace UNSWThink
{
   /// <summary>
   /// Main windows form of the application
   /// </summary>
   public partial class StartForm : Form
   {
      // objects
      private DBConnection dbConnection;
      private LoadingForm loadingScreen;
      private ArrayList viewResponsesForms;
      private ArrayList graphResponsesForms;
      private ViewResponsesForm enquiryForm;
      private GraphResponsesTabForm graphTabForm;
      private ViewResponsesTabForm viewTabForm;
      
      // data
      private DataSet instructorData;
      private DataTable relatedQuestions;
      private DataTable relatedResponses;
      private DataTable relatedEnquiries;

      // combobox data
      private ArrayList courseIDs;
      private ArrayList courseStrings;
      private ArrayList weekStrings;
      private ArrayList classStrings;

      // states
      private bool connected;
      private bool loggedIn;
      private int instructorID;
      private int selectedCourseID;
      private int selectedWeek;
      private int selectedClassID;
      private int prevSelectedClassID;
      private int prevResponseRecordOffset;
      private int responseRecordOffset;
      private int prevEnquiryRecordOffset;
      private int enquiryRecordOffset;
      private RetrievalState currentState;

      /// <summary>
      /// Default constructor
      /// </summary>
      public StartForm()
      {
         InitializeComponent();

         connected = false;
         loggedIn = false;
         dbConnection = new DBConnection();
         loadingScreen = new LoadingForm();

         Init();
      }

      #region WINDOWS FORM EVENTS

      private void StartForm_Load(object sender, EventArgs e)
      {
         this.Show();

         PerformConnect();

         PerformLogin();
      }

      private void StartForm_FormClosing(object sender, FormClosingEventArgs e)
      {
         bool connectionClosed = AttpemtClose();
         if (!connectionClosed)
         {
            e.Cancel = true;
         }
      }

      #endregion

      #region CONTROL EVENTS

      private void buttonEdit_Click(object sender, EventArgs e)
      {
         wizardPagesMain.SelectTab("tabPageEdit");
      }

      private void buttonRun_Click(object sender, EventArgs e)
      {
         wizardPagesMain.SelectTab("tabPageRun");
      }

      private void toolStripButtonEdit_Click(object sender, EventArgs e)
      {
         wizardPagesMain.SelectTab("tabPageEdit");
      }

      private void toolStripButtonRun_Click(object sender, EventArgs e)
      {
         wizardPagesMain.SelectTab("tabPageRun");
      }

      /// <summary>
      /// Executes when the login menu button in the menu strip is pressed
      /// </summary>
      /// <param name="sender">object sender</param>
      /// <param name="e">EventArgs e</param>
      private void toolStripMenuItemLogin_Click(object sender, EventArgs e)
      {
         if (connected)
         {
            if (loggedIn)
            {
               string confirmMessage = "Are you sure you want to logout?";
               DialogResult result = MessageBox.Show(confirmMessage, "Confirm logout", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

               if (result == DialogResult.Yes)
               {
                  connected = !dbConnection.Disconnect();
                  PerformConnect();
                  loggedIn = false;
                  ToggleConnectMenuLabel();

                  Init();
               }
            }
            else
            {
               PerformLogin();
            }
         }
         else
         {
            if (loggedIn)
            {
               PerformConnect();
               ToggleConnectMenuLabel();
            }
            else
            {
               PerformConnect();
               PerformLogin();
            }
         }
      }

      private void toolStripMenuItemExit_Click(object sender, EventArgs e)
      {
         this.Close();
      }

      private void toolStripMenuItemAbout_Click(object sender, EventArgs e)
      {
         AboutForm about = new AboutForm();
         about.Show();
      }

      /// <summary>
      /// Event that controls hiding and showing the sidebar when the button is clicked
      /// </summary>
      /// <param name="sender">object sender</param>
      /// <param name="e">EventArgs e</param>
      private void toolStripButtonMode_Click(object sender, EventArgs e)
      {
         if (splitContainer1.SplitterDistance == 108)
         {
            splitContainer1.SplitterDistance = 24;
            toolStripButtonMode.Image = Properties.Resources.agt_forward;
            toolStripButtonMode.Text = "Show Modes";
            toolStripContainer2.TopToolStripPanelVisible = false;
            toolStripContainer2.TopToolStripPanel.Controls.Remove(toolStripSidebar);
            toolStripContainer2.LeftToolStripPanelVisible = true;
            toolStripContainer2.LeftToolStripPanel.Controls.Add(toolStripSidebar);
            toolStripSidebar.TextDirection = ToolStripTextDirection.Vertical90;
            toolStripButtonMode.TextImageRelation = TextImageRelation.ImageAboveText;
         }
         else
         {
            splitContainer1.SplitterDistance = 108;
            toolStripButtonMode.Image = Properties.Resources.agt_back;
            toolStripButtonMode.Text = "Hide Modes";
            toolStripContainer2.TopToolStripPanelVisible = true;
            toolStripContainer2.TopToolStripPanel.Controls.Add(toolStripSidebar);
            toolStripContainer2.LeftToolStripPanelVisible = false;
            toolStripContainer2.LeftToolStripPanel.Controls.Remove(toolStripSidebar);
            toolStripSidebar.TextDirection = ToolStripTextDirection.Horizontal;
            toolStripButtonMode.TextImageRelation = TextImageRelation.ImageBeforeText;
         }
      }

      /// <summary>
      /// Executed when the index of the course combo box in edit page changes
      /// </summary>
      /// <param name="sender">object sender</param>
      /// <param name="e">EventArgs e</param>
      private void comboBoxEditCourse_SelectedIndexChanged(object sender, EventArgs e)
      {
         ComboBoxCourseIndexChanged(comboBoxEditCourse.SelectedIndex);
      }

      /// <summary>
      /// Executed when the index of the week combo box in edit page changes
      /// </summary>
      /// <param name="sender">object sender</param>
      /// <param name="e">EventArgs e</param>
      private void comboBoxEditWeek_SelectedIndexChanged(object sender, EventArgs e)
      {
         ComboBoxWeekIndexChanged(comboBoxEditWeek.SelectedIndex);
      }

      /// <summary>
      /// Executed when the index of the class combo box in edit page changes
      /// </summary>
      /// <param name="sender">object sender</param>
      /// <param name="e">EventArgs e</param>
      private void comboBoxEditClass_SelectedIndexChanged(object sender, EventArgs e)
      {
         ComboBoxClassIndexChanged(comboBoxEditClass.SelectedIndex);
      }

      private void dataGridViewRun_CellClick(object sender, DataGridViewCellEventArgs e)
      {
         // Ignore clicks that are not on button cells. 
         if (e.RowIndex >= 0)
         {
            int questionID = Int32.Parse(dataGridViewRun.Rows[e.RowIndex].Cells["id"].Value.ToString());
            QuestionType qType = HelperMethods.QuestionTypeStringToEnum(dataGridViewRun.Rows[e.RowIndex].Cells["type"].Value.ToString());
            int questionNum = Int32.Parse(dataGridViewRun.Rows[e.RowIndex].Cells["number"].Value.ToString());

            // if the view button was clicked, create a ViewResponsesForm and display it
            if (e.ColumnIndex == dataGridViewRun.Columns["view"].Index)
            {
               ViewResponsesForm viewResponses = new ViewResponsesForm(Defs.RESPONSE_MODE, questionID, relatedResponses);
               viewResponses.Text = "Viewing responses for question " + questionNum;
               viewResponsesForms.Add(viewResponses); // add to form list
               viewResponses.Show();
            }
            // if the graph button was clicked, create a GraphResponsesForm ans display it
            else if (e.ColumnIndex == dataGridViewRun.Columns["graph"].Index)
            {
               GraphResponsesForm graphResponses = new GraphResponsesForm(questionID, questionNum, qType, 
                  instructorData.Tables["Answer"], relatedResponses);
               graphResponses.Text = "Displaying graph for question " + questionNum;
               graphResponsesForms.Add(graphResponses); // add to form list
               graphResponses.Show();
            }
         }
      }

      /// <summary>
      /// Executed when a cell in the question data grid view is clicked
      /// </summary>
      /// <param name="sender">object sender</param>
      /// <param name="e">DataGridViewCellEventArgs e</param>
      private void dataGridViewEdit_CellClick(object sender, DataGridViewCellEventArgs e)
      {
         // Ignore clicks that are not on button cells. 
         if (e.RowIndex >= 0)
         {
            int questionID = Int32.Parse(dataGridViewEdit.Rows[e.RowIndex].Cells["id"].Value.ToString());
            string questionNum = dataGridViewEdit.Rows[e.RowIndex].Cells["number"].Value.ToString();

            // if the edit button was clicked, create AddEditQuestionForm and display it
            if (e.ColumnIndex == dataGridViewEdit.Columns["edit"].Index)
            {
               AddEditQuestionForm questionForm = new AddEditQuestionForm(Defs.EDIT_MODE, dbConnection, 
                  questionID, instructorData.Tables["Question"], instructorData.Tables["Answer"]);
               questionForm.Text = "Editing question " + questionNum;
               questionForm.ShowDialog();

               // once the form is closed, update all necessary controls
               relatedQuestions = GetQuestionDataTable(selectedClassID);

               dataGridViewEdit.DataSource = relatedQuestions;
               dataGridViewEdit.Sort(dataGridViewEdit.Columns["number"], ListSortDirection.Ascending);

               dataGridViewRun.DataSource = relatedQuestions;
               dataGridViewRun.Sort(dataGridViewRun.Columns["number"], ListSortDirection.Ascending);
            }
            // if the  delete button was clicked, delete all related references to the 
            // selected question (database and program's memory)
            else if (e.ColumnIndex == dataGridViewEdit.Columns["delete"].Index)
            {
               string confirmMsg = "Are you sure you want to delete question " + questionNum + 
                  "?\nDeleting a question will also delete all related answers and responses.";
               DialogResult confirmDelete = MessageBox.Show(confirmMsg, "Delete question?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

               if (confirmDelete == DialogResult.Yes)
               {
                  bool deleted = false;

                  // delete all answers relating to the question that's to be deleted
                  deleted = dbConnection.DeleteRecord("Answer", new string[1] { "question" }, new object[1] { questionID });
                  if (deleted)
                  {
                     for (int i = 0; i < instructorData.Tables["Answer"].Rows.Count; i++)
                     {
                        if ((int)instructorData.Tables["Answer"].Rows[i]["question"] == questionID)
                        {
                           instructorData.Tables["Answer"].Rows.RemoveAt(i);
                           i--;
                        }
                     }
                  }

                  //delete all responses relating to the question that's to be deleted
                  deleted = dbConnection.DeleteRecord("Response", new string[1] { "question" }, new object[1] { questionID });
                  if (deleted)
                  {
                     // delete responses from program's memory
                     for (int i = 0; i < relatedResponses.Rows.Count; i++)
                     {
                        if ((int)relatedResponses.Rows[i]["question"] == questionID)
                        {
                           relatedResponses.Rows.RemoveAt(i);
                           i--;
                        }
                     }
                  }

                  deleted = dbConnection.DeleteRecord("Question", Int32.Parse(dataGridViewEdit.Rows[e.RowIndex].Cells["id"].Value.ToString()));
                  if (deleted)
                  {
                     // update question numbers for all other questions 
                     // i.e. if q2 was deleted, set q3 as q2 etc
                     bool updated = false;
                     HelperMethods.UpdateQuestionNumbers(relatedQuestions, questionID);
                     for (int i = 0; i < relatedQuestions.Rows.Count; i++)
                     {
                        int tempQuestionID = Int32.Parse(relatedQuestions.Rows[i]["id"].ToString());
                        updated = dbConnection.UpdateRecord("Question", "number", tempQuestionID, 
                           Int32.Parse(relatedQuestions.Rows[i]["number"].ToString()));
                     }
                     if (updated)
                     {
                        HelperMethods.UpdateQuestionNumbers(instructorData.Tables["Question"], questionID);
                     }

                     // delete from program's memory
                     for (int i = 0; i < instructorData.Tables["Question"].Rows.Count; i++)
                     {
                        if ((int)instructorData.Tables["Question"].Rows[i]["id"] == questionID)
                        {
                           instructorData.Tables["Question"].Rows.RemoveAt(i);
                        }
                     }

                     // update question data grid view
                     dataGridViewEdit.Rows.RemoveAt(e.RowIndex);

                     relatedQuestions = GetQuestionDataTable(selectedClassID);
                     dataGridViewEdit.DataSource = relatedQuestions;
                     dataGridViewEdit.Sort(dataGridViewEdit.Columns["number"], ListSortDirection.Ascending);

                     dataGridViewRun.DataSource = relatedQuestions;
                     dataGridViewRun.Sort(dataGridViewRun.Columns["number"], ListSortDirection.Ascending);
                  }
               }
            }
         }
      }

      private void buttonEditQuestionAdd_Click(object sender, EventArgs e)
      {
         if (loggedIn)
         {
            AddEditQuestionForm newQuestion = new AddEditQuestionForm(Defs.ADD_MODE, dbConnection,
               selectedClassID, instructorData.Tables["Question"], instructorData.Tables["Answer"]);
            newQuestion.NewNumber = relatedQuestions.Rows.Count + 1;
            newQuestion.Text = "Adding question to " + comboBoxEditClass.SelectedItem.ToString() +
               " (" + comboBoxEditCourse.SelectedItem.ToString() + ")";
            newQuestion.ShowDialog();

            // once the form is closed, update all necessary controls
            relatedQuestions = GetQuestionDataTable(selectedClassID);

            dataGridViewEdit.DataSource = relatedQuestions;
            dataGridViewEdit.Sort(dataGridViewEdit.Columns["number"], ListSortDirection.Ascending);

            dataGridViewRun.DataSource = relatedQuestions;
            dataGridViewRun.Sort(dataGridViewRun.Columns["number"], ListSortDirection.Ascending);

            // update totals
            if (currentState == RetrievalState.Running)
            {
               TallyResponses();
            }
         }
         else
         {
            MessageBox.Show("Cannot add a question", "Not logged in",
               MessageBoxButtons.OK, MessageBoxIcon.Information);
         }
      }

      private void buttonEditReorder_Click(object sender, EventArgs e)
      {
         if (loggedIn)
         {
            ReorderQuestionsForm reorderForm = new ReorderQuestionsForm(dbConnection,
               instructorData.Tables["Question"], relatedQuestions);
            reorderForm.Text = "Reordering questions of " + comboBoxEditClass.SelectedItem.ToString();
            reorderForm.ShowDialog();

            // once the form is closed, update all necessary controls
            relatedQuestions = GetQuestionDataTable(selectedClassID);

            dataGridViewEdit.DataSource = relatedQuestions;
            dataGridViewEdit.Sort(dataGridViewEdit.Columns["number"], ListSortDirection.Ascending);

            dataGridViewRun.DataSource = relatedQuestions;
            dataGridViewRun.Sort(dataGridViewRun.Columns["number"], ListSortDirection.Ascending);
         }
         else
         {
            MessageBox.Show("Cannot reorder", "Not logged in",
               MessageBoxButtons.OK, MessageBoxIcon.Information);
         }
      }

      private void buttonRunRetrieval_Click(object sender, EventArgs e)
      {
         if (currentState == RetrievalState.Idle)
         {
            currentState = RetrievalState.Starting;
            ToggleRetrieveButton(currentState);
            loadingScreen = new LoadingForm();
            backgroundWorkerResponse.RunWorkerAsync();
            loadingScreen.ShowDialog();
         }
         else if (currentState == RetrievalState.Starting)
         {
            currentState = RetrievalState.Running;
            ToggleRetrieveButton(currentState);
         }
         else if (currentState == RetrievalState.Running)
         {
            currentState = RetrievalState.Stopping;
            ToggleRetrieveButton(currentState);
         }
         else if (currentState == RetrievalState.Stopping)
         {
            currentState = RetrievalState.Idle;
            ToggleRetrieveButton(currentState);
         }
      }

      private void buttonRunEnquiry_Click(object sender, EventArgs e)
      {
         if (relatedEnquiries.Rows.Count > 0) 
         {
            if ((enquiryForm != null))
            {
               if (enquiryForm.Visible)
               {
                  enquiryForm.Activate();
               }
               else
               {
                  enquiryForm = new ViewResponsesForm(Defs.ENQUIRY_MODE, 0, relatedEnquiries);
                  enquiryForm.Text = "Enquiries for " + comboBoxEditClass.SelectedItem.ToString() +
                     " (" + comboBoxEditCourse.SelectedItem.ToString() + ")";
                  enquiryForm.Show();
               }
            }
            else
            {
               enquiryForm = new ViewResponsesForm(Defs.ENQUIRY_MODE, 0, relatedEnquiries);
               enquiryForm.Text = "Enquiries for " + comboBoxEditClass.SelectedItem.ToString() +
                     " (" + comboBoxEditCourse.SelectedItem.ToString() + ")";
               enquiryForm.Show();
            }
         }
         else
         {
            MessageBox.Show("There are no enquiries to display", "No equiries",
               MessageBoxButtons.OK, MessageBoxIcon.Information);
         }
      }
      
      private void buttonEditClassAdd_Click(object sender, EventArgs e)
      {
         AddEditClassForm classForm = new AddEditClassForm(Defs.ADD_MODE, dbConnection,
            instructorID, selectedClassID, courseIDs, courseStrings, instructorData);
         classForm.Text = "Creating class for " + comboBoxEditCourse.SelectedItem.ToString();
         classForm.Icon = Properties.Resources.window_new_icon;
         classForm.ShowDialog();

         ComboBoxCourseInit();
      }

      private void buttonEditClassEdit_Click(object sender, EventArgs e)
      {
         AddEditClassForm classForm = new AddEditClassForm(Defs.EDIT_MODE, dbConnection,
            instructorID, selectedClassID, courseIDs, courseStrings, instructorData);
         classForm.Text = "Editing class " + comboBoxEditClass.SelectedItem.ToString();
         classForm.Icon = Properties.Resources.lin_agt_wrench_icon;
         classForm.ShowDialog();

         ComboBoxCourseInit();
      }

      #endregion

      #region THEADING EVENTS

      private void backgroundWorkerLoginInit_DoWork(object sender, DoWorkEventArgs e)
      {
         e.Result = dbConnection.GetAllInstructorRelatedData(instructorID);
      }

      private void backgroundWorkerLoginInit_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
         instructorData = (DataSet)e.Result;
         loadingScreen.Close();

         ComboBoxCourseInit();
      }

      private void backgroundWorkerResponse_DoWork(object sender, DoWorkEventArgs e)
      {
         // init offsets according to whether the selectedClassID has changed or not
         if ((prevSelectedClassID != selectedClassID) || (relatedResponses.Rows.Count == 0))
         {
            prevSelectedClassID = selectedClassID;
            prevResponseRecordOffset = 0;
            responseRecordOffset = 0;
            prevEnquiryRecordOffset = 0;
            enquiryRecordOffset = 0;
         }
         else
         {
            responseRecordOffset = relatedResponses.Rows.Count;
            enquiryRecordOffset = relatedEnquiries.Rows.Count;
         }

         // initially, retrieve all related responses
         dbConnection.GetAllResponses(responseRecordOffset, selectedClassID, relatedResponses);
         dbConnection.GetAllEnquiries(enquiryRecordOffset, selectedClassID, relatedEnquiries);
         // update the UI (i.e. close the loading form)
         backgroundWorkerResponse.ReportProgress(0);

         // wait until the loading form has closed since the main thread (UI thread) may be slower
         // than this background thread
         while (currentState == RetrievalState.Starting) ;

         // loop that constantly retrieves new responses according to an offset
         while (currentState == RetrievalState.Running)
         {
            // preserve the original offset
            prevResponseRecordOffset = responseRecordOffset;
            prevEnquiryRecordOffset = enquiryRecordOffset;
            // get new offset, possibly as a result of the response table growing in size
            responseRecordOffset = relatedResponses.Rows.Count;
            enquiryRecordOffset = relatedEnquiries.Rows.Count;
            // get more data
            dbConnection.GetAllResponses(responseRecordOffset, selectedClassID, relatedResponses);
            dbConnection.GetAllEnquiries(enquiryRecordOffset, selectedClassID, relatedEnquiries);
            
            // update totals
            backgroundWorkerResponse.ReportProgress(0);

            // put thread to sleed for a defined amount of time (defined in Defs.cs)
            Thread.Sleep(Defs.THREAD_SLEEP_LENGTH);
         }
      }

      private void backgroundWorkerResponse_ProgressChanged(object sender, ProgressChangedEventArgs e)
      {
         // close loading form
         if (currentState == RetrievalState.Starting)
         {
            if (loadingScreen != null)
            {
               loadingScreen.Close();
            }

            currentState = RetrievalState.Running;
         }
         // if new responses have been retrieved, update the totals
         // else do nothing
         else if (currentState == RetrievalState.Running)
         {
            //Console.WriteLine("Reporting Progress! " + prevResponseRecordOffset.ToString() + " " + 
            //   responseRecordOffset.ToString());
            if ((prevResponseRecordOffset != responseRecordOffset) ||
                (prevEnquiryRecordOffset != enquiryRecordOffset))
            {
               //Console.WriteLine(responseRecordOffset.ToString() + " new responses");
               TallyResponses();
               RefreshDataDisplayForms();
            }
         }
         // change state to 'Idle' when state is currently 'Stopping'
         else if (currentState == RetrievalState.Stopping)
         {
            currentState = RetrievalState.Idle;
         }

         ToggleRetrieveButton(currentState);
      }

      private void backgroundWorkerResponse_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
         currentState = RetrievalState.Idle;
         ToggleRetrieveButton(currentState);
      }

      private void timerDBConnection_Tick(object sender, EventArgs e)
      {
         if (!dbConnection.CheckConnection())
         {
            timerDBConnection.Stop();
            string msg = "Connection to database server has been lost.\nWould you like to reconnect?";
            DialogResult result = MessageBox.Show(msg, "Reconnect?", MessageBoxButtons.YesNo, MessageBoxIcon.Hand);

            if (result == DialogResult.Yes)
            {
               PerformConnect();
               PerformLogin();
            }
            else
            {
               connected = !dbConnection.Disconnect();
               PerformConnect();
               loggedIn = false;
               ToggleConnectMenuLabel();

               Init();
            }
         }
      }

      #endregion

      #region HELPER METHODS

      /// <summary>
      /// Resets various controls and global variables to an 'initial' state
      /// </summary>
      private void Init()
      {
         // create or clear
         if (instructorData != null)
         {
            instructorData.Clear();
         }

         if (relatedResponses != null)
         {
            relatedResponses.Clear();
         }
         else
         {
            relatedResponses = new DataTable("Response");
         }

         if (relatedEnquiries != null)
         {
            relatedEnquiries.Clear();
         }
         else
         {
            relatedEnquiries = new DataTable("Enquiry");
         }

         if (courseIDs == null)
         {
            courseIDs = new ArrayList();
         }
         else
         {
            courseIDs.Clear();
         }

         if (courseStrings == null)
         {
            courseStrings = new ArrayList();
         }
         else
         {
            courseStrings.Clear();
         }

         if (weekStrings == null)
         {
            weekStrings = new ArrayList();
         }
         else
         {
            weekStrings.Clear();
         }

         if (classStrings == null)
         {
            classStrings = new ArrayList();
         }
         else
         {
            classStrings.Clear();
         }

         if (viewResponsesForms == null)
         {
            viewResponsesForms = new ArrayList();
         }
         else
         {
            viewResponsesForms.Clear();
         }

         if (graphResponsesForms == null)
         {
            graphResponsesForms = new ArrayList();
         }
         else
         {
            graphResponsesForms.Clear();
         }

         // reset IDs
         instructorID = 0;
         selectedCourseID = 0;
         selectedWeek = 0;
         selectedClassID = 0;
         prevSelectedClassID = 0;

         // reset other variables
         prevResponseRecordOffset = 0;
         responseRecordOffset = 0;
         currentState = RetrievalState.Idle;
         
         // reset labels
         labelEditClassAccountValue.Text = Defs.DEFAULT_NA_STRING;

         // disable buttons
         buttonEditClassAdd.Enabled = false;
         buttonEditClassEdit.Enabled = false;
         buttonEditQuestionAdd.Enabled = false;
         buttonEditReorder.Enabled = false;
         buttonRunEnquiry.Enabled = false;
         buttonRunGraph.Enabled = false;
         buttonRunResponse.Enabled = false;
         buttonRunRetrieval.Enabled = false;

         // reset question data grid view
         dataGridViewEdit.DataSource = null;
         dataGridViewEdit.Columns.Clear();
         dataGridViewRun.DataSource = null;
         dataGridViewRun.Columns.Clear();

         // reset edit page controls
         comboBoxEditCourse.Enabled = false;
         comboBoxEditCourse.DataSource = null;
         comboBoxEditWeek.Enabled = false;
         comboBoxEditWeek.DataSource = null;
         comboBoxEditClass.Enabled = false;
         comboBoxEditClass.DataSource = null;
         textBoxEditClassName.Text = String.Empty;
         textBoxEditClassComments.Text = String.Empty;

         // reset run page controls
         comboBoxRunCourse.Enabled = false;
         comboBoxRunCourse.DataSource = null;
         comboBoxRunWeek.Enabled = false;
         comboBoxRunWeek.DataSource = null;
         comboBoxRunClass.Enabled = false;
         comboBoxRunClass.DataSource = null;
         textBoxRunClassName.Text = String.Empty;
         textBoxRunClassComments.Text = String.Empty;
      }

      /// <summary>
      /// Toggles the text on toolStripMenuItemLogin
      /// </summary>
      public void ToggleConnectMenuLabel()
      {
         if (toolStripMenuItemLogin.Text == "Login")
         {
            toolStripMenuItemLogin.Text = "Logout";
         }
         else
         {
            toolStripMenuItemLogin.Text = "Login";
         }
      }

      /// <summary>
      /// Handles the endabling/disabling of controls according to the state of the retrieval thread
      /// </summary>
      /// <param name="state">
      /// State that is to be changed
      /// </param>
      private void ToggleRetrieveButton(RetrievalState state)
      {
         if (loggedIn)
         {
            switch (state)
            {
               case RetrievalState.Idle:
                  comboBoxEditCourse.Enabled = true;
                  comboBoxEditWeek.Enabled = true;
                  comboBoxEditClass.Enabled = true;
                  comboBoxRunCourse.Enabled = true;
                  comboBoxRunWeek.Enabled = true;
                  comboBoxRunClass.Enabled = true;
                  buttonEditClassAdd.Enabled = true;
                  buttonEditReorder.Enabled = true;
                  dataGridViewEdit.Columns["delete"].Visible = true;

                  buttonRunRetrieval.Text = "Retrieve Responses";
                  buttonRunRetrieval.Image = Properties.Resources.agt_update_drivers;
                  buttonRunRetrieval.Enabled = true;
                  break;
               case RetrievalState.Starting:
                  comboBoxEditCourse.Enabled = false;
                  comboBoxEditWeek.Enabled = false;
                  comboBoxEditClass.Enabled = false;
                  comboBoxRunCourse.Enabled = false;
                  comboBoxRunWeek.Enabled = false;
                  comboBoxRunClass.Enabled = false;
                  buttonEditClassAdd.Enabled = false;
                  buttonEditReorder.Enabled = false;
                  dataGridViewEdit.Columns["delete"].Visible = false;

                  buttonRunRetrieval.Text = "Starting...";
                  buttonRunRetrieval.Image = Properties.Resources.spinning_icon_small;
                  buttonRunRetrieval.Enabled = false;
                  break;
               case RetrievalState.Running:
                  buttonRunRetrieval.Text = "Stop retrieval";
                  buttonRunRetrieval.Enabled = true;
                  break;
               case RetrievalState.Stopping:
                  buttonRunRetrieval.Text = "Stopping...";
                  buttonRunRetrieval.Enabled = false;
                  break;
               default:
                  buttonRunRetrieval.Text = "Run Retrieval";
                  buttonRunRetrieval.Image = null;
                  buttonRunRetrieval.Enabled = true;
                  break;
            }
         }
         else
         {
            MessageBox.Show("Cannot retrieve data", "Not logged in", 
               MessageBoxButtons.OK, MessageBoxIcon.Information);
         }
      }

      /// <summary>
      /// Peforms connection to the database
      /// </summary>
      private void PerformConnect()
      {
         bool attemptReconnect = true;

         while (attemptReconnect)
         {
            connected = dbConnection.Connect();

            if (!connected)
            {
               DialogResult result = MessageBox.Show("Could not establish a connection to the database server", "No connection", MessageBoxButtons.RetryCancel, MessageBoxIcon.Hand);
               if (result == DialogResult.Retry)
               {
                  attemptReconnect = true;
               }
               else
               {
                  attemptReconnect = false;
               }
            }
            else
            {
               attemptReconnect = false;
            }
         }
      }

      /// <summary>
      /// Displays login form to initiate login process
      /// </summary>
      private void PerformLogin()
      {
         if (connected)
         {
            LoginForm loginForm = new LoginForm(dbConnection);
            loginForm.ShowDialog(this);

            if (loggedIn)
            {
               loadingScreen = new LoadingForm();
               backgroundWorkerLoginInit.RunWorkerAsync();
               loadingScreen.ShowDialog();
               ToggleConnectMenuLabel();

               timerDBConnection.Start();
            }
         }
      }

      /// <summary>
      /// Attempt to perform a disconnection from a connected database.
      /// </summary>
      private bool AttpemtClose()
      {
         bool closed = false;

         if (connected)
         {
            bool result = dbConnection.Disconnect();

            if (result)
            {
               closed = result;
               //MessageBox.Show("Connection to database is now closed", "Disconnect Confirmed", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
               CloseDataDisplayForms();

               timerDBConnection.Stop();
            }
            else
            {
               closed = !result;
               MessageBox.Show("Connection to database could not be closed properly", "Disconnect Problem", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
         }
         else
         {
            closed = true;
         }

         return closed;
      }

      /// <summary>
      /// Initialises the course combobox 
      /// </summary>
      private void ComboBoxCourseInit()
      {
         // clear course string and ID array lists
         courseStrings.Clear();
         courseIDs.Clear();
         comboBoxEditCourse.DataSource = null;
         comboBoxRunCourse.DataSource = null;

         // clear labels
         labelEditClassAccountValue.Text = Defs.DEFAULT_NA_STRING;

         // perform data search & data join
         if ((instructorData.Tables.Contains("Course")) && 
             (instructorData.Tables.Contains("Term")) &&
             (instructorData.Tables.Contains("Subject")))
         {
            for (int i = 0; i < instructorData.Tables["Term"].Rows.Count; i++)
            {
               int termID = (int)instructorData.Tables["Term"].Rows[i]["id"];
               string session = instructorData.Tables["Term"].Rows[i]["session"].ToString();
               DateTime startDate = (DateTime)instructorData.Tables["Term"].Rows[i]["startdate"];
               DateTime finishDate = (DateTime)instructorData.Tables["Term"].Rows[i]["finishdate"];

               for (int j = 0; j < instructorData.Tables["Course"].Rows.Count; j++)
               {
                  int courseID = (int)instructorData.Tables["Course"].Rows[j]["id"];
                  int subject = (int)instructorData.Tables["Course"].Rows[j]["subject"];
                  int term = (int)instructorData.Tables["Course"].Rows[j]["term"];

                  if (termID == term)
                  {
                     for (int k = 0; k < instructorData.Tables["Subject"].Rows.Count; k++)
                     {
                        int subjectID = (int)instructorData.Tables["Subject"].Rows[k]["id"];
                        string name = instructorData.Tables["Subject"].Rows[k]["name"].ToString();
                        string code = instructorData.Tables["Subject"].Rows[k]["code"].ToString();

                        if (subject == subjectID)
                        {
                           //string item = code + " - " + name + " (" + session + "/" + startDate.Year.ToString() + ")";
                           string item = code + " (" + session + "/" + startDate.Year.ToString() + ")";
                           // add string and ID to corresponding lists
                           courseStrings.Add(item);
                           courseStrings.Sort();
                           int insertIndex = courseStrings.BinarySearch(item);

                           courseIDs.Insert(insertIndex, courseID);
                           break;
                        }
                     }
                  }
               }
            }
         }

         // if the list contains data, enable/disable corresponding controls
         if (courseStrings.Count > 0)
         {
            comboBoxEditCourse.Enabled = true;
            comboBoxEditWeek.Enabled = false;
            comboBoxEditClass.Enabled = false;

            comboBoxRunCourse.Enabled = true;
            comboBoxRunWeek.Enabled = false;
            comboBoxRunClass.Enabled = false;

            labelEditClassAccountValue.Text = String.Empty;
         }

         // set related comboboxes' data source to their respective string lists
         comboBoxEditCourse.DataSource = courseStrings;
         comboBoxRunCourse.DataSource = courseStrings;
      }

      /// <summary>
      /// Initialises class combobox respective to the selected item in the course combobox
      /// </summary>
      /// <param name="selectedIndex"></param>
      private void ComboBoxCourseIndexChanged(int selectedIndex)
      {
         if (selectedIndex >= 0)
         {
            // clear week string list
            weekStrings.Clear();

            // clear related responses list
            relatedResponses.Clear();

            // clear labels
            labelEditClassAccountValue.Text = String.Empty;

            // clear questions data grid view
            dataGridViewEdit.DataSource = null;
            dataGridViewEdit.Columns.Clear();

            dataGridViewRun.DataSource = null;
            dataGridViewRun.Columns.Clear();

            // enable/disable edit page class buttons
            buttonEditClassAdd.Enabled = true;
            buttonEditClassEdit.Enabled = false;
            buttonEditQuestionAdd.Enabled = false;
            buttonEditReorder.Enabled = false;
            buttonRunRetrieval.Enabled = false;
            buttonRunEnquiry.Enabled = false;
            buttonRunGraph.Enabled = false;
            buttonRunResponse.Enabled = false;

            // empty textboxes
            textBoxEditClassName.Text = String.Empty;
            textBoxEditClassComments.Text = String.Empty;
            textBoxRunClassName.Text = String.Empty;
            textBoxRunClassComments.Text = String.Empty;

            // change various comboboxes' states
            comboBoxEditWeek.DataSource = null;
            comboBoxEditClass.Enabled = false;
            comboBoxEditClass.DataSource = null;
            comboBoxRunWeek.DataSource = null;
            comboBoxRunClass.Enabled = false;
            comboBoxRunClass.DataSource = null;

            // fill week combo box with week strings
            selectedCourseID = (int)courseIDs[selectedIndex];
            ArrayList weeks = new ArrayList();

            // find all distinct week numbers
            if (instructorData.Tables.Contains("Class"))
            {
               for (int i = 0; i < instructorData.Tables["Class"].Rows.Count; i++)
               {
                  if (selectedCourseID == (int)instructorData.Tables["Class"].Rows[i]["course"])
                  {
                     int weekNum = (int)instructorData.Tables["Class"].Rows[i]["week"];
                     if (!weeks.Contains(weekNum))
                     {
                        weeks.Add(weekNum);
                     }
                  }
               }
            }

            // generate desired strings to represent each week
            if (weeks.Count > 0)
            {
               weeks.Sort();
               foreach (int weekNum in weeks)
               {
                  weekStrings.Add(HelperMethods.WeekNumberToString(weekNum));
               }
            }

            // if list contains data, enable/disable corresponding controls
            if (weekStrings.Count > 0)
            {
               comboBoxEditCourse.Enabled = true;
               comboBoxEditWeek.Enabled = true;
               comboBoxEditClass.Enabled = false;

               comboBoxRunCourse.Enabled = true;
               comboBoxRunWeek.Enabled = true;
               comboBoxRunClass.Enabled = false;

               labelEditClassAccountValue.Text = String.Empty;
            }

            // set related comboboxes' data source to their respoective string lists
            comboBoxEditWeek.DataSource = weekStrings;
            comboBoxRunWeek.DataSource = weekStrings;
         }
      }

      /// <summary>
      /// Initialises the class combobox respective to the selected item in the week combobox
      /// </summary>
      /// <param name="selectedIndex"></param>
      private void ComboBoxWeekIndexChanged(int selectedIndex)
      {
         if (selectedIndex >= 0)
         {
            // clear class string list
            classStrings.Clear();

            // clear related responses list
            relatedResponses.Clear();

            // clear labels
            labelEditClassAccountValue.Text = String.Empty;

            // clear questions data grid view
            dataGridViewEdit.DataSource = null;
            dataGridViewEdit.Columns.Clear();

            dataGridViewRun.DataSource = null;
            dataGridViewRun.Columns.Clear();

            // enable/disable edit page class buttons
            buttonEditClassAdd.Enabled = true;
            buttonEditClassEdit.Enabled = false;
            buttonEditQuestionAdd.Enabled = false;
            buttonEditReorder.Enabled = false;
            buttonRunRetrieval.Enabled = false;
            buttonRunEnquiry.Enabled = false;
            buttonRunGraph.Enabled = false;
            buttonRunResponse.Enabled = false;

            // empty textboxes
            textBoxEditClassName.Text = String.Empty;
            textBoxEditClassComments.Text = String.Empty;
            textBoxRunClassName.Text = String.Empty;
            textBoxRunClassComments.Text = String.Empty;

            // change various comboboxes' states
            comboBoxEditClass.DataSource = null;
            comboBoxRunClass.DataSource = null;

            // parse selected week string to number
            selectedWeek = HelperMethods.WeekStringToNumber(comboBoxEditWeek.Items[selectedIndex].ToString());

            // find and add all class relating to selected week and course
            if (instructorData.Tables.Contains("Class"))
            {
               DataTable classTable = instructorData.Tables["Class"];
               for (int i = 0; i < classTable.Rows.Count; i++)
               {
                  if (((int)classTable.Rows[i]["course"] == selectedCourseID) &&
                     ((int)classTable.Rows[i]["week"] == selectedWeek))
                  {
                     DateTime startingTime = (DateTime)classTable.Rows[i]["startTime"];
                     classStrings.Add(startingTime.ToString());
                  }
               }
            }

            // if list contains data, enable/disable corresponding controls
            if (classStrings.Count > 0)
            {
               comboBoxEditCourse.Enabled = true;
               comboBoxEditWeek.Enabled = true;
               comboBoxEditClass.Enabled = true;

               comboBoxRunCourse.Enabled = true;
               comboBoxRunWeek.Enabled = true;
               comboBoxRunClass.Enabled = true;
            }

            // set related comboboxes' data source to their respoective string lists
            comboBoxEditClass.DataSource = classStrings;
            comboBoxRunClass.DataSource = classStrings;
         }
      }

      /// <summary>
      /// Initialises the various controls respective to the selected item in the class combobox
      /// </summary>
      private void ComboBoxClassIndexChanged(int selectedIndex)
      {
         if (selectedIndex >= 0)
         {
            // clear related responses list
            relatedResponses.Clear();

            // enable/disable edit page class buttons
            buttonEditClassAdd.Enabled = true;
            buttonEditClassEdit.Enabled = true;
            buttonEditQuestionAdd.Enabled = true;
            buttonEditReorder.Enabled = true;
            buttonRunRetrieval.Enabled = true;
            buttonRunEnquiry.Enabled = true;
            buttonRunGraph.Enabled = true;
            buttonRunResponse.Enabled = true;

            string selectedItem = comboBoxEditClass.Items[selectedIndex].ToString();
            selectedClassID = GetSelectedClassID(selectedItem);

            if (selectedClassID > 0)
            {
               // clear question data gird view columns to prevent multiple button columns
               dataGridViewEdit.Columns.Clear();
               dataGridViewRun.Columns.Clear();

               // find other information about selected class and display the 
               // information (includes related questions)
               if (instructorData.Tables.Contains("Class"))
               {
                  DataTable classTable = instructorData.Tables["Class"];

                  // loop through all questions
                  for (int i = 0; i < classTable.Rows.Count; i++)
                  {
                     if ((int)classTable.Rows[i]["id"] == selectedClassID)
                     {
                        // set class name and comments
                        string className = classTable.Rows[i]["name"].ToString();
                        string classComments = classTable.Rows[i]["comments"].ToString();
                        textBoxEditClassName.Text = className;
                        textBoxEditClassComments.Text = classComments;
                        textBoxRunClassName.Text = className;
                        textBoxRunClassComments.Text = classComments;

                        // set data source with related questions and sort by question number (ascending)
                        relatedQuestions = GetQuestionDataTable(selectedClassID);
                        dataGridViewEdit.DataSource = relatedQuestions;
                        dataGridViewEdit.Sort(dataGridViewEdit.Columns["number"], ListSortDirection.Ascending);

                        dataGridViewRun.DataSource = relatedQuestions;
                        dataGridViewRun.Sort(dataGridViewRun.Columns["number"], ListSortDirection.Ascending);

                        // don't show id, class, and image columns
                        if (dataGridViewEdit.Columns.Contains("id") &&
                            dataGridViewEdit.Columns.Contains("class") &&
                            dataGridViewEdit.Columns.Contains("image"))
                        {
                           dataGridViewEdit.Columns["id"].Visible = false;
                           dataGridViewEdit.Columns["class"].Visible = false;
                           dataGridViewEdit.Columns["image"].Visible = false;
                        }

                        if (dataGridViewRun.Columns.Contains("id") &&
                            dataGridViewRun.Columns.Contains("class") &&
                            dataGridViewRun.Columns.Contains("image"))
                        {
                           dataGridViewRun.Columns["id"].Visible = false;
                           dataGridViewRun.Columns["class"].Visible = false;
                           dataGridViewRun.Columns["image"].Visible = false;
                        }

                        // set the autosize modes of remaining columns
                        if (dataGridViewEdit.Columns.Contains("number") &&
                            dataGridViewEdit.Columns.Contains("description") &&
                            dataGridViewEdit.Columns.Contains("type"))
                        {
                           dataGridViewEdit.Columns["number"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
                           dataGridViewEdit.Columns["description"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                           dataGridViewEdit.Columns["type"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
                        }

                        if (dataGridViewRun.Columns.Contains("number") &&
                            dataGridViewRun.Columns.Contains("description") &&
                            dataGridViewRun.Columns.Contains("type"))
                        {
                           dataGridViewRun.Columns["number"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
                           dataGridViewRun.Columns["description"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                           dataGridViewRun.Columns["type"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
                        }

                        // create edit data grid view button column
                        DataGridViewButtonColumn buttonColumnEdit = new DataGridViewButtonColumn();
                        buttonColumnEdit.HeaderText = "";
                        buttonColumnEdit.Name = "edit";
                        buttonColumnEdit.Text = "Edit";
                        buttonColumnEdit.ToolTipText = "Edit the selected question";
                        buttonColumnEdit.UseColumnTextForButtonValue = true;
                        buttonColumnEdit.Width = 45;
                        buttonColumnEdit.Resizable = DataGridViewTriState.False;
                        dataGridViewEdit.Columns.Add(buttonColumnEdit);

                        // create delete data grid view button column
                        DataGridViewButtonColumn buttonColumnDelete = new DataGridViewButtonColumn();
                        buttonColumnDelete.HeaderText = "";
                        buttonColumnDelete.Name = "delete";
                        buttonColumnDelete.Text = "Delete";
                        buttonColumnDelete.ToolTipText = "Delete the selected question";
                        buttonColumnDelete.UseColumnTextForButtonValue = true;
                        buttonColumnDelete.Width = 45;
                        buttonColumnDelete.Resizable = DataGridViewTriState.False;
                        dataGridViewEdit.Columns.Add(buttonColumnDelete);

                        // create total data grid view column
                        DataGridViewColumn totalColumn = new DataGridViewColumn(new DataGridViewTextBoxCell());
                        totalColumn.HeaderText = "total";
                        totalColumn.Name = "total";
                        totalColumn.ValueType = typeof(int);
                        totalColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
                        dataGridViewRun.Columns.Add(totalColumn);
                        //dataGridViewRun.Columns["total"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;

                        // create view data grid view button column
                        DataGridViewButtonColumn buttonColumnView = new DataGridViewButtonColumn();
                        buttonColumnView.HeaderText = "";
                        buttonColumnView.Name = "view";
                        buttonColumnView.Text = "View";
                        buttonColumnView.ToolTipText = "View the responses to the selected question";
                        buttonColumnView.UseColumnTextForButtonValue = true;
                        buttonColumnView.Width = 45;
                        buttonColumnView.Resizable = DataGridViewTriState.False;
                        dataGridViewRun.Columns.Add(buttonColumnView);

                        // create graph data grid view button column
                        DataGridViewButtonColumn buttonColumnGraph = new DataGridViewButtonColumn();
                        buttonColumnGraph.HeaderText = "";
                        buttonColumnGraph.Name = "graph";
                        buttonColumnGraph.Text = "Graph";
                        buttonColumnGraph.ToolTipText = "Graph the responses";
                        buttonColumnGraph.UseColumnTextForButtonValue = true;
                        buttonColumnGraph.Width = 45;
                        buttonColumnGraph.Resizable = DataGridViewTriState.False;
                        dataGridViewRun.Columns.Add(buttonColumnGraph);

                        dataGridViewRun.Columns["view"].Visible = false;
                        dataGridViewRun.Columns["graph"].Visible = false;
                     }
                  }
               }

               if (instructorData.Tables.Contains("ClassAccount"))
               {
                  //if (HelperMethods.IDExists(instructorData.Tables["ClassAccount"], selectedClassID))
                  if (HelperMethods.ValueExists(instructorData.Tables["ClassAccount"], "class", selectedClassID.ToString()))
                  {
                     labelEditClassAccountValue.Text = "Yes";
                  }
                  else
                  {
                     labelEditClassAccountValue.Text = "No";
                  }
               }
            }
         }
      }

      /// <summary>
      /// Updates the run data grid view with totals of the related responses
      /// </summary>
      private void TallyResponses()
      {
         for (int i = 0; i < dataGridViewRun.Rows.Count; i++)
         {
            dataGridViewRun.Columns["total"].ReadOnly = false;
            dataGridViewRun.Rows[i].Cells["total"].Value = GetTotalResponses((int)dataGridViewRun.Rows[i].Cells["id"].Value);
            dataGridViewRun.Columns["total"].ReadOnly = true;
         }

         dataGridViewRun.Columns["view"].Visible = true;
         dataGridViewRun.Columns["graph"].Visible = true;
      }

      /// <summary>
      /// Performs the tally calculation
      /// </summary>
      /// <param name="questionID"></param>
      /// <returns></returns>
      private int GetTotalResponses(int questionID)
      {
         int result = 0;
         if (HelperMethods.CheckColumnsExists(relatedResponses, Defs.RESPONSE_COLUMN_NAMES))
         {
            for (int i = 0; i < relatedResponses.Rows.Count; i++)
            {
               if ((int)relatedResponses.Rows[i]["question"] == questionID)
               {
                  result++;
               }
            }
         }
         return result;
      }

      /// <summary>
      /// Refreshes all of the view, graph, and enquiry forms so that newly retrieved data 
      /// can be displayed
      /// </summary>
      private void RefreshDataDisplayForms()
      {
         // refresh ViewResponseForms
         if (viewResponsesForms.Count > 0)
         {
            foreach (ViewResponsesForm vf in viewResponsesForms)
            {
               vf.UpdateList();
            }
         }

         // refresh GraphResponseForms
         if (graphResponsesForms.Count > 0)
         {
            foreach (GraphResponsesForm gf in graphResponsesForms)
            {
               gf.UpdateGraph();
            }
         }

         // refresh enquiry form (should be a ViewResponseForm)
         if (enquiryForm != null)
         {
            enquiryForm.UpdateList();
         }

         if (viewTabForm != null)
         {
            viewTabForm.UpdateList();
         }

         if (graphTabForm != null)
         {
            graphTabForm.UpdateGraph();
         }
      }

      // Closes all of the view, graph, and enquiry forms
      private void CloseDataDisplayForms()
      {
         // closes all of the ViewResponseForms
         if (viewResponsesForms.Count > 0)
         {
            foreach (ViewResponsesForm vf in viewResponsesForms)
            {
               vf.Close();
            }
         }

         // closes all of the GraphResponseForms
         if (graphResponsesForms.Count > 0)
         {
            foreach (GraphResponsesForm gf in graphResponsesForms)
            {
               gf.Close();
            }
         }

         // close enquiry form
         if (enquiryForm != null)
         {
            enquiryForm.Close();
         }

         if (viewTabForm != null)
         {
            viewTabForm.Close();
         }

         if (graphTabForm != null)
         {
            graphTabForm.Close();
         }
      }

      /// <summary>
      /// Gets corresponding class ID from a given class starting time
      /// </summary>
      /// <param name="classStartTime">
      /// Class starting time in a string format
      /// </param>
      /// <returns>
      /// Class ID
      /// </returns>
      private int GetSelectedClassID(string classStartTime)
      {
         if (instructorData.Tables.Contains("Class"))
         {
            DataTable classTable = instructorData.Tables["Class"];
            for (int i = 0; i < classTable.Rows.Count; i++)
            {
               DateTime tempTime = (DateTime)classTable.Rows[i]["starttime"];
               if (tempTime.ToString() == classStartTime)
               {
                  return (int)classTable.Rows[i]["id"];
               }
            }
         }

         return 0;
      }

      /// <summary>
      /// Gets all of the questions relating to a class ID from the instructor data set 
      /// </summary>
      /// <param name="classID">
      /// Class ID corresponding to the requested questions
      /// </param>
      /// <returns>
      /// Data table of questions relating to a selected class
      /// </returns>
      private DataTable GetQuestionDataTable(int classID)
      {
         DataTable questions = new DataTable("Question");

         if (instructorData.Tables.Contains("Question"))
         {
            // get all column names from instructorData and add to new data table
            DataTable completeTable = instructorData.Tables["Question"];
            for (int i = 0; i < completeTable.Columns.Count; i++)
            {
               questions.Columns.Add(completeTable.Columns[i].ColumnName, completeTable.Columns[i].DataType);
            }

            // loop through all questions from instructorData and only add questions
            // with the same class ID to the new data table
            for (int i = 0; i < completeTable.Rows.Count; i++)
            {
               if ((int)completeTable.Rows[i]["class"] == classID)
               {
                  object[] currentRow = completeTable.Rows[i].ItemArray;
                  
                  questions.Rows.Add(currentRow);
               }
            }
         }
         return questions;
      }

      #endregion

      #region PROPERTIES

      /// <summary>
      /// Gets or sets whether the user is logged in
      /// </summary>
      public bool LoggedIn
      {
         get
         {
            return loggedIn;
         }
         set
         {
            loggedIn = value;
         }
      }

      /// <summary>
      /// Gets or sets the instructor ID
      /// </summary>
      public int InstructorID
      {
         get
         {
            return instructorID;
         }
         set
         {
            instructorID = value;
         }
      }

      /// <summary>
      /// Gets or sets the view enquiry button's enabled property
      /// </summary>
      public bool EnquiryButtonEnable
      {
         get
         {
            return buttonRunEnquiry.Enabled;
         }
         set
         {
            buttonRunEnquiry.Enabled = value;
         }
      }

      #endregion

      private void buttonRunGraph_Click(object sender, EventArgs e)
      {
         if (relatedResponses.Rows.Count > 0)
         {
            if ((graphTabForm != null))
            {
               if (graphTabForm.Visible)
               {
                  graphTabForm.Activate();
               }
               else
               {
                  graphTabForm = new GraphResponsesTabForm(relatedQuestions, instructorData.Tables["Answer"], relatedResponses);
                  graphTabForm.Text = "Graphs for " + comboBoxEditClass.SelectedItem.ToString() +
                     " - " + comboBoxEditCourse.SelectedItem.ToString();
                  graphTabForm.Show();
               }
            }
            else
            {
               graphTabForm = new GraphResponsesTabForm(relatedQuestions, instructorData.Tables["Answer"], relatedResponses);
               graphTabForm.Text = "Graphs for " + comboBoxEditClass.SelectedItem.ToString() +
                  " - " + comboBoxEditCourse.SelectedItem.ToString();
               graphTabForm.Show();
            }
         }
         else
         {
            MessageBox.Show("There are no responses to display", "No responses",
               MessageBoxButtons.OK, MessageBoxIcon.Information);
         }
      }

      private void buttonRunResponse_Click(object sender, EventArgs e)
      {
         if (relatedResponses.Rows.Count > 0)
         {
            if ((viewTabForm != null))
            {
               if (viewTabForm.Visible)
               {
                  viewTabForm.Activate();
               }
               else
               {
                  viewTabForm = new ViewResponsesTabForm(relatedQuestions, relatedResponses);
                  viewTabForm.Text = "Responses for " + comboBoxEditClass.SelectedItem.ToString() +
                     " - " + comboBoxEditCourse.SelectedItem.ToString();
                  viewTabForm.Show();
               }
            }
            else
            {
               viewTabForm = new ViewResponsesTabForm(relatedQuestions, relatedResponses);
               viewTabForm.Text = "Responses for " + comboBoxEditClass.SelectedItem.ToString() +
                  " - " + comboBoxEditCourse.SelectedItem.ToString();
               viewTabForm.Show();
            }
         }
         else
         {
            MessageBox.Show("There are no responses to display", "No responses",
               MessageBoxButtons.OK, MessageBoxIcon.Information);
         }
      }

   }
}
